from django.shortcuts import render
from rest_framework import viewsets
from rest_framework import permissions
from certificate_manager.models import *
from certificate_manager.serializers import *
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.status import HTTP_202_ACCEPTED, HTTP_406_NOT_ACCEPTABLE, HTTP_404_NOT_FOUND
from rest_framework.decorators import action
from rest_framework.permissions import BasePermission, SAFE_METHODS
from rest_framework.exceptions import NotFound, NotAcceptable
from datetime import date

class JoinerShowOrForbid(BasePermission):

        def has_permission(self, request, view):
                if request.method in ['PUT', 'PATCH']:
                        # 不允许更新Cert
                        return False
                elif request.method in SAFE_METHODS:
                        return True
                elif request.method == 'POST':
                        # 任何人都能提交证书，这个没有限制
                        return request.user.is_authenticated

        def has_object_permission(self, request, view, cert):
                if cert.all_accept:
                        return True
                else:
                        return request.user.is_authenticated and cert.join_set.filter(user=request.user).exists()

class CertViewSet(viewsets.ModelViewSet):
        queryset = Cert.objects.all()
        serializer_class = CertSerializer
        permission_classes = [JoinerShowOrForbid]
        # 我们希望按照权限添加，其他用户不能看到未完全审批的Cert，只有管理员与项目相关的人才能看到

        def list(self, request):
                # 我们要指定用户
                user = request.user
                param = request.query_params

                if 'user' in param:
                    user = User.objects.get(uid=param['user'])

                if 'all_accept' in param:
                        certs = self.list_cur_user_unaccpetd_certs(user, param['all_accept'])
                else:
                        if 'start' not in param and 'count' not in param:
                            raise NotAcceptable('start and count is needed')
                        start = int(param['start'])
                        count = int(param['count'])
                        results = self.queryset.filter(all_accept=True)
                        certs = results[start:min(len(results), start + count)]
                return Response(CertSerializer(certs, many=True).data)


        def list_cur_user_unaccpetd_certs(self, user, all_accept):
                # 正好，如果all_accept为真就把当前用户的通过的所有证书都返回来
                # 如何实现这样复杂的查询呢？
                joins = user.join_set.filter(cert__all_accept=all_accept)
                return [join.cert for join in joins]
        

        @action(detail=True, methods=['POST'])
        def join(self, request, pk=None):
                user = request.user
                # 但是这里事实上有问题，我们应该根据最新的没有完全审批的priority得到对应的join
                if user.join_set.filter(cert_id=pk).count() != 1:
                    raise NotAcceptable(detail='暂不支持：当前用户在审批列表出现多次')

                join = user.join_set.get(cert_id=pk)
                ccate = join.cert.cate
                today = date.today()
                if ccate.start_date <= today and today <= ccate.end_date:
                        pass
                else:
                        raise NotAcceptable(detail='Time not permit')
                # 注意，如果有操作之后就不能再同意了
                if join.status == Join.UNKNOWN and join.cert.all_accept == False:
                        # 只有这个时候可以改变状态
                        # 序列化请求对象
                        join_request_serializer = JoinChangeSerializer(data=request.data)
                        join_request_serializer.is_valid(raise_exception=True)  
                        join_request = join_request_serializer.validated_data
                        join.status = Join.ACCEPT if join_request['approve'] else Join.REJECT
                        if not join_request['approve']:
                                join.msg = join_request['msg']
                        # 更新一下当前时间
                        join.acc_date = date.today()
                        join.save()
                        
                        # 下面我们要更新证书的状态
                        cert = join.cert
                        if cert.join_set.exclude(status=Join.ACCEPT).count() == 0:
                                # 说明都同意了
                                cert.all_accept = True
                                cert.save()
                        return Response(CertSerializer(cert).data, HTTP_202_ACCEPTED)

                else:
                        raise NotFound
